package com.yiboshi.rehrs.util;


import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.Date;
import java.util.Locale;

/**
 * 日期工具
 *
 * @description:
 */
public class DateUtils {

    //数据库格式的日期
    public static final String SQL_MONTH = "yyyy-MM";
    public static final String SQL_DATE = "yyyy-MM-dd";
    public static final String SQL_TIME = "yyyy-MM-dd HH:mm:ss";
    public static final String SQL_TIMESTAMP = "yyyy-MM-dd HH:mm:ss.SS";

    //斜杠格式的日期
    public static final String DATE = "yyyy/MM/dd";
    public static final String TIMESTAMP = "yyyy/MM/dd HH:mm:ss.SS";
    public static final String TIMESTAMP_SHORT = "yyyy/MM/dd HH:mm";
    public static final String TIME = "HH:mm:ss";
    public static final String TIME_SHORT = "HH:mm";

    //不常用日期格式
    public static final String CH_TIME = "yyyy年MM月dd日HH时mm分";
    public static final String CHINESEDATE = "yyyy年MM月dd日";
    public static final String DATE_TIME = "yyyyMMddHHmmss";
    public static final String DATE_TIME_DETAIL = "yyyyMMddHHmmssSS";
    public static final String DATE_DAY = "yyyyMMdd";
    public static final String DATE_HOUR = "yyyyMMddHH";
    public static final String YEAR = "yyyy";

    /**
     * 防止被实例化
     */
    private DateUtils() {

    }

    /**
     * Date转LocalDateTime
     * 使用系统时区
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        return instant.atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * LocalDateTime转Date
     * 使用系统时区
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }

    /**
     * 日期转字符串
     *
     * @param localDateTime
     * @param pattern
     * @return
     */
    public static String dateTimeToStr(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return localDateTime.format(formatter);
    }
    public static String dateTimeToStr(LocalDateTime localDateTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(SQL_TIME);
        return localDateTime.format(formatter);
    }


    public static Long dateTimeToLong(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return Long.valueOf(localDateTime.format(formatter));
    }

    /**
     * @param localDateTime
     * @return int 20210421
     */
    public static Integer dateTimeToInt(LocalDateTime localDateTime) {
        return dateTimeToLong(localDateTime, DATE_DAY).intValue();
    }

    /**
     * 日期转字符串
     *
     * @param localDate
     * @param pattern
     * @return
     */
    public static String dateToStr(LocalDate localDate, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return localDate.format(formatter);
    }

    /**
     * yyyy-MM-dd 格式
     *
     * @param currentDate
     * @return
     */
    public static String dateToStr(Date currentDate) {
        if (currentDate == null) {
            return null;
        }
        // 创建一个SimpleDateFormat实例，指定所需日期时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(SQL_DATE);
        // 使用format方法将Date对象转换为字符串
        String formattedDate = sdf.format(currentDate);
        return formattedDate;
    }

    public static String dateToStr(Date currentDate, String pattern) {
        // 创建一个SimpleDateFormat实例，指定所需日期时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        // 使用format方法将Date对象转换为字符串
        String formattedDate = sdf.format(currentDate);
        return formattedDate;
    }


    /**
     * 将字符串日期解析为java.time.LocalDateTime
     *
     * @param dateTimeStr
     * @param pattern
     * @return
     */
    public static LocalDateTime strToLocalDateTime(String dateTimeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(dateTimeStr, formatter);
    }

    /**
     * 将字符串日期解析为java.time.LocalDateTime
     *
     * @param dateTimeStr
     * @param pattern
     * @return
     */
    public static LocalDate strToLocalDate(String dateTimeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(dateTimeStr, formatter);
    }

    public static LocalDateTime strToLocalDateTime(String dateTimeStr) {
        if (StringUtils.isEmpty(dateTimeStr)) {
            return null;
        }
        String[] dateTimeStrDayTime = dateTimeStr.split(" ");
        String day = dateTimeStrDayTime[0];
        String[] split = null;
        if (day.contains("-")) {
            split = day.split("-");
        }
        if (day.contains("/")) {
            split = day.split("/");
        }
        if (split == null) {
            return null;
        }
        if (split.length < 3) {
            return null;
        }
        try {
            if (dateTimeStrDayTime.length == 1) {
                return LocalDateTime.of(Integer.valueOf(split[0]), Integer.valueOf(split[1]), Integer.valueOf(split[2]), 0, 0, 0);
            }
            if (dateTimeStrDayTime.length == 2) {
                String time = dateTimeStrDayTime[1];
                String[] timeArray = time.split(":");
                return LocalDateTime.of(Integer.valueOf(split[0]), Integer.valueOf(split[1]), Integer.valueOf(split[2]),
                        Integer.valueOf(timeArray[0]), Integer.valueOf(timeArray[1]), Integer.valueOf(timeArray[2]));
            }

        } catch (Exception e) {

        }
        return null;
    }


    /**
     * 开始日期，补齐" 00:00:00"
     *
     * @param localDateTime
     * @return
     */
    public static LocalDateTime getStartDateTimeWithHMS(LocalDateTime localDateTime) {
        return LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN);
    }


    /**
     * 结束日期，补齐" 23:59:59"
     *
     * @param localDateTime
     * @return
     */
    public static LocalDateTime getEndDateWithHMS(LocalDateTime localDateTime) {
        return LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX);
    }


    public static LocalDateTime getAfterYears(LocalDateTime localDateTime, int count) {
        return localDateTime.plusYears(count);
    }

    public static LocalDateTime getAfterMonths(LocalDateTime localDateTime, int count) {
        return localDateTime.plusMonths(count);
    }

    public static LocalDateTime getAfterDays(LocalDateTime localDateTime, int count) {
        return localDateTime.plusDays(count);
    }

    public static LocalDateTime getAfterMinutes(LocalDateTime localDateTime, int count) {
        return localDateTime.plusMinutes(count);
    }

    public static LocalDateTime getAfterSeconds(LocalDateTime localDateTime, int count) {
        return localDateTime.plusSeconds(count);
    }


    /**
     * 获得当前年的第一天
     *
     * @param
     * @return
     */
    public static LocalDateTime getYearFirstDay(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 获得当前年的最后一天
     *
     * @param
     * @return
     */
    public static LocalDateTime getYearLastDay(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.lastDayOfYear());
    }


    /**
     * 获得当前月的第一天
     *
     * @param
     * @return
     */
    public static LocalDateTime getMonthFirstDay(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获得当前月的最后一天
     *
     * @param
     * @return
     */
    public static LocalDateTime getMonthLastDay(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.lastDayOfMonth());
    }


    /**
     * 获得当前星期的第一天
     *
     * @param localDateTime
     * @param locale        默认Locale.CHINA 周日为一周的第一天
     * @return
     */
    public static LocalDateTime getWeekFirstDay(LocalDateTime localDateTime, Locale locale) {
        return localDateTime.with(WeekFields.of(locale == null ? Locale.CHINA : locale).dayOfWeek(), 1);
    }

    /**
     * 获得当前星期的最后一天
     *
     * @param localDateTime
     * @param locale        默认默认Locale.CHINA 周日为一周的第一天
     * @return
     */
    public static LocalDateTime getWeekLastDay(LocalDateTime localDateTime, Locale locale) {
        return localDateTime.with(WeekFields.of(locale == null ? Locale.CHINA : locale).dayOfWeek(), 7);
    }


    /**
     * 计算两个日期之间相差年数
     *
     * @param smallDateTime 较小的时间
     * @param bigDateTime   较大的时间
     * @return 相差年数
     */
    public static int getYearDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.YEARS);
    }

    /**
     * 计算两个日期之间相差月数
     *
     * @param smallDateTime 较小的时间
     * @param bigDateTime   较大的时间
     * @return 相差月数
     */
    public static int getMonthDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.MONTHS);
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smallDateTime 较小的时间
     * @param bigDateTime   较大的时间
     * @return 相差天数
     */
    public static int getDayDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.DAYS);
    }

    /**
     * 计算两个日期之间相差小时数
     *
     * @param smallDateTime 较小的时间
     * @param bigDateTime   较大的时间
     * @return 相差小时数
     */
    public static int getHourDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.HOURS);
    }

    /**
     * 计算两个日期之间相差分钟数
     *
     * @param smallDateTime
     * @param bigDateTime
     * @return 相差分钟数
     */
    public static int getMinutesDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.MINUTES);
    }

    /**
     * 计算两个日期之间相差秒数
     *
     * @param smallDateTime
     * @param bigDateTime
     * @return 相差秒数
     */
    public static int getSecondsDiff(LocalDateTime smallDateTime, LocalDateTime bigDateTime) {
        return (int) smallDateTime.until(bigDateTime, ChronoUnit.SECONDS);
    }

    /**
     * yyyyMMdd转数字
     **/
    public static Integer toInt(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        String s = dateToStr(localDate, DATE_DAY);
        return Integer.valueOf(s);
    }

    /**
     * yyyyMMdd转日期
     **/
    public static LocalDate intToLocalDate(int yyyyMMdd) {
        return strToLocalDate(yyyyMMdd + "", DATE_DAY);
    }

    public static LocalDateTime  plusDays(LocalDateTime localDateTime,int days) {
        LocalDateTime now = LocalDateTime.now();
        if(localDateTime==null||localDateTime.isBefore(now)){
            localDateTime = now;
        }
        return localDateTime.plusDays(days);
    }

}
